﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;

namespace OK.SCOM.Authoring.Tools.MPElementsExtract
{
	internal class MPElementTypeReport: MPElementTypeBase
	{
		internal enum ExtractionMode { Reports, LinkedReports }

		private string m_name;
		private string m_rdl;
		private string m_rpdl;
		private string m_parameters;

		private XmlNode m_rdlEmbedCandidate;
		private XmlNode m_rpdlEmbedCandidate;
		private XmlNode m_parametersEmbedCandidate;

		internal override string Name
		{
			get
			{
				return ((Mode==ExtractionMode.LinkedReports)?"Linked ":"")+"Report (placemarks are not used - content will be replaced on embedding)";
			}
		}

		internal override bool SupportsEmbed
		{
			get { return true; }
		}

		internal override bool SupportsExtractReplaceWithPlaceMarks
		{
			get {	return true; }
		}

		internal ExtractionMode Mode { get; set; }

		internal MPElementTypeReport(string baseDirectory, string extractBaseDirectory)
			: base(baseDirectory, extractBaseDirectory)
		{
			m_name = "";
			m_rdl = "";
			m_rpdl = "";
			m_parameters = "";
		}

		protected override void ProcessSingleNodeBeforeChildren(System.Xml.XmlNode node, ParseAction action)
		{
			if ((node.Name == "Report" && Mode == ExtractionMode.Reports && node.ParentNode.Name == "Reports") ||
				(node.Name == "LinkedReport" && Mode == ExtractionMode.LinkedReports && node.ParentNode.Name == "LinkedReports"))
			{
				m_rdl = "";
				m_rpdl = "";
				m_parameters = "";
				m_name = node.Attributes["ID"].Value;
				m_rdlEmbedCandidate = null;
				m_rpdlEmbedCandidate = null;
				m_parametersEmbedCandidate = null;
			}
			else if (node.Name == "ParameterBlock" && (node.ParentNode.Name == "Report" || node.ParentNode.Name == "LinkedReport"))
			{
				m_rpdl = node.OuterXml;
			}
			else if (node.Name == "Definition")
			{
				m_rdl = node.InnerXml;
			}
			else if (node.Name == "Parameters")
			{
				m_parameters = node.OuterXml;
			}

	
			if (node.Name == "Definition" && node.ParentNode.Name == "Report" && action == ParseAction.Embed)
			{
				m_rdlEmbedCandidate = node;
			}

			if (node.Name == "ParameterBlock" && (node.ParentNode.Name == "Report" || node.ParentNode.Name == "LinkedReport")
				&& action == ParseAction.Embed)
			{
				m_rpdlEmbedCandidate = node;
			}

			if (node.Name == "Parameters" && node.ParentNode.Name == "LinkedReport" && action == ParseAction.Embed)
			{
				m_parametersEmbedCandidate = node;
			}

		}

		protected override void ProcessSingleNodeAfterChild(System.Xml.XmlNode node, ParseAction action)
		{
			//
		}

		protected override void ProcessSingleNodeAfterChildren(System.Xml.XmlNode node, ParseAction action)
		{
			if ((node.Name == "Report" && Mode==ExtractionMode.Reports && node.ParentNode.Name == "Reports") ||
				(node.Name == "LinkedReport" && Mode == ExtractionMode.LinkedReports && node.ParentNode.Name == "LinkedReports"))
			{
				if (action == ParseAction.ExtractNoPlaceMarks || action == ParseAction.ExtractReplaceWithPlaceMarks)
				{
					Console.WriteLine(String.Format("Report found: {0}", m_name));
					if (m_rdl.Length > 0 && Mode==ExtractionMode.Reports)
					{
						SaveXml(m_rdl, m_name + ".rdl");
						Console.WriteLine(String.Format("Definition saved ({0} bytes)", m_rdl.Length));
					}
					if (m_rpdl.Length > 0)
					{
						SaveXml(m_rpdl, m_name + ".rpdl");
						Console.WriteLine(String.Format("ParameterBlock saved ({0} bytes)", m_rpdl.Length));
					}
					if (m_parameters.Length > 0 && Mode == ExtractionMode.LinkedReports)
					{
						SaveXml(m_parameters, m_name + ".parameters");
						Console.WriteLine(String.Format("Parameters saved ({0} bytes)", m_parameters.Length));
					}

					m_name = "";
					m_rdl = "";
					m_rpdl = "";
					m_parameters = "";
				}
				else if (action == ParseAction.Embed)
				{
					if (Mode == ExtractionMode.Reports) EmbedRdl(m_rdlEmbedCandidate, node);
					EmbedRpdl(m_rpdlEmbedCandidate, node);
					if (Mode == ExtractionMode.LinkedReports) EmbedParameters(m_parametersEmbedCandidate, node);
				}
			}

		}

		private void EmbedRdl(XmlNode node, XmlNode reportnode)
		{
			Console.WriteLine(String.Format("Embeding {0}.rdl", Path.Combine(ExtractBaseDirectory, m_name)));
			try
			{
				string content = LoadXmlNoDeclaration(Path.Combine(ExtractBaseDirectory, m_name) + ".rdl");

				XmlNode rdlNode = node;

				if (rdlNode == null)
				{
					rdlNode = reportnode.OwnerDocument.CreateNode("Element", "Definition", "");
					reportnode.AppendChild(rdlNode);
				}
				rdlNode.InnerXml = content;
			}
			catch (Exception ex)
			{
				Console.WriteLine(String.Format("WARNING: {0}. SKIPPED!!!", ex.Message));
			}
		}

		private void EmbedRpdl(XmlNode node, XmlNode reportnode)
		{
			Console.WriteLine(String.Format("Embeding {0}.rpdl", Path.Combine(ExtractBaseDirectory, m_name)));
			try
			{
				string content = LoadXmlNoDeclaration(Path.Combine(ExtractBaseDirectory, m_name) + ".rpdl");

				XmlDocument rpdl = new XmlDocument();
				rpdl.LoadXml(content);
				XmlNode srcNode = rpdl.DocumentElement;

				XmlNode newNode = reportnode.OwnerDocument.ImportNode(srcNode, true);
				if (node == null)
				{
					if (Mode == ExtractionMode.Reports)
					{
						if (m_rdlEmbedCandidate != null)
						{
							reportnode.InsertBefore(newNode, m_rdlEmbedCandidate);
						}
						else throw new Exception("Cannot embed rpdl - Definition element not found");
					}
					else if (Mode == ExtractionMode.LinkedReports)
					{
						if (m_parametersEmbedCandidate == null) reportnode.AppendChild(newNode);
						else reportnode.InsertBefore(newNode, m_parametersEmbedCandidate);
					}
				}
				else reportnode.ReplaceChild(newNode, node);
			}
			catch (Exception ex)
			{
				Console.WriteLine(String.Format("WARNING: {0}. SKIPPED!!!",ex.Message));
			}
		}

		private void EmbedParameters(XmlNode node, XmlNode reportnode)
		{
			Console.WriteLine(String.Format("Embeding {0}.parameters", Path.Combine(ExtractBaseDirectory, m_name)));
			try
			{
				string content = LoadXmlNoDeclaration(Path.Combine(ExtractBaseDirectory, m_name) + ".parameters");

				XmlDocument param = new XmlDocument();
				param.LoadXml(content);
				XmlNode srcNode = param.DocumentElement;

				XmlNode newNode = reportnode.OwnerDocument.ImportNode(srcNode, true);
				if (node == null) reportnode.AppendChild(newNode);
				else reportnode.ReplaceChild(newNode, node);
			}
			catch (Exception ex)
			{
				Console.WriteLine(String.Format("WARNING: {0}. SKIPPED!!!", ex.Message));
			}
		}

	}
}
